#include"string.h"

namespace my_string
{
	string::string(const string& str)//拷贝构造函数
	{
		str_ = new char[str.capacity_ + 1];//给`\0`多开一个空间
		strcpy(str_, str.str_);

		capacity_ = str.capacity_;
		size_ = str.size_;
	}

	string::string(const char* s)//使用c字符串构造
	{
		size_ = strlen(s);
		capacity_ = size_;
		str_ = new char[capacity_ + 1];

		memcpy(str_, s, size_ + 1);//\0也要拷贝进去
	}

	string::string(size_t n, char c)//使用n个字符c来构造string类
	{
		size_ = n;
		capacity_ = size_;
		str_ = new char[capacity_ + 1];//给\0预留一个空间

		memset(str_, c, n);//逐字节初始化
		str_[size_] = '\0';
	}

	void string::resize(size_t n, char c)
	{
		if (n > size_)
		{
			//先考虑是否扩容
			if (n > capacity_)//需要扩容
			{
				char* tmp = new char[n + 1];
				memcpy(tmp, str_, size_);//把之前的内容拷贝进来
				memset(tmp + size_, c, n - size_);
				size_ = n;
				capacity_ = n;
				tmp[size_] = '\0';
				delete[] str_;//把之前空间的内存释放掉

				str_ = tmp;
			}
			else//不需要扩容，直接初始化后面空间的内容即可
			{
				memset(str_ + size_, c, n - size_);
				size_ = n;
				str_[size_] = '\0';
			}
		}
		else//n < size_,只需要改size_
		{
			size_ = n;
			str_[size_] = '\0';
		}
	}

	void string::shrink_to_fit()
	{
		char* tmp = new char[size_ + 1];
		capacity_ = size_;
		memcpy(tmp, str_, size_ + 1);//把原先的字符串（包括\0）都拷贝给tmp

		delete[] str_;//释放原来空间的内存
		str_ = tmp;
	}

	void string::clear()
	{
		size_ = 0;
		if (str_ != nullptr)
		  str_[0] = '\0';
	}

	char& string::operator[] (size_t pos)
	{
		assert(pos <= size_);

		return str_[pos];
	}
	const char& string::operator[] (size_t pos) const
	{
		assert(pos <= size_);

		return str_[pos];
	}

	string& string::operator+= (const string& str)
	{
		//看是否需要扩容
		if (str.size() + size_ > capacity_)//需要
		{
			char* tmp = new char[str.size() + size_ + 1];//保存之前的字符串
			memcpy(tmp, str_, size_);
			memcpy(tmp + size_, str.str_, str.size_ + 1); //str（包括\0）都拷贝给tmp
			//更新成员变量
			size_ += str.size();
			capacity_ = size_;

			delete[] str_;//释放之前申请的的空间
			str_ = tmp;
		}

		else//不需要
		{
			memcpy(str_ + size_, str.str_, str.size_ + 1);//把\0也copy进去
			size_ += str.size();
			str_[size_] = '\0';
		}

		return *this;
	}
	string& string::operator+= (const char* s)
	{
		int length = strlen(s);
		//看是否需要扩容
		if (length + size_ > capacity_)//需要
		{
			char* tmp = new char[size_ + length + 1];//保存之前的字符串
			memcpy(tmp, str_, size_);
			memcpy(tmp + size_, s, length + 1);////字符串s（包括\0）都拷贝给tmp
			//更新成员变量
			size_ += length;
			capacity_ = size_;

			delete[] str_;//释放之前申请的的空间
			str_ = tmp;
		}

		else//不需要
		{
			memcpy(str_ + size_, s, length + 1);//把\0也copy进去
			size_ += length;
		}

		return *this;
	}
	string& string::operator+= (char c)
	{
		//先看是否需要扩容
		if (size_ + 1 > capacity_)
		{
			capacity_ = capacity_ == 0 ? 4 : capacity_ * 1.5;//扩容到原先的1.5倍
			char* tmp = new char[capacity_ + 1];
			if (str_ != nullptr)
				strcpy(tmp, str_);
			tmp[size_++] = c;
			tmp[size_] = '\0';
			if (str_ != nullptr)
				delete[] str_;

			str_ = tmp;
		}

		else
		{
			str_[size_++] = c;
			str_[size_] = '\0';
		}
		return *this;
	}

	string& string::append(const string& str)//
	{
		*this += str;
		return *this;
	}
	string& string::append(const char* s)
	{
		*this += s;
		return *this;
	}
	string& string::append(size_t n, char c)
	{
		string tmp(n, c);
		*this += tmp;

		return *this;
	}


	string& string::insert(size_t pos, const string& str)
	{
		//是否需要扩容
		if (size_ + str.size() > capacity_)
		{
			capacity_ = size_ + str.size();
			char* tmp = new char[capacity_ + 1];
			strcpy(tmp, str_);

			////先把pos位置及其之后的字符后移
			memcpy(tmp + pos + str.size(), tmp + pos, size_ - pos + 1);//把\0也拷贝进去
			memcpy(tmp + pos, str.str_, str.size());

			delete[] str_;
			str_ = tmp;
			size_ += str.size();
		}
		else
		{
			size_ += str.size();
			//先把pos位置及其之后的字符后移
			memcpy(str_ + pos + str.size(), str_ + pos, size_ - pos + 1);//把\0也拷贝进去
			memcpy(str_ + pos, str.str_, str.size());
		}

		return *this;
	}
	string::iterator string::insert(iterator p, char c)
	{
		//需要扩容
		int pos_ = p - begin();//提前保存，防止迭代器失效
		if (size_ == capacity_)
		{
			capacity_ = capacity_ == 0 ? 4 : capacity_ * 1.5;
			char* tmp = new char[capacity_ + 1];
			strcpy(tmp, str_);

			int pos = pos_;
			for (int i = size_; i >= pos; --i)//包括\0都后移一位
				tmp[i + 1] = tmp[i];
			tmp[pos] = c;
			delete[] str_;

			str_ = tmp;
			size_++;
		}
		else
		{
			int pos = pos_;
			for (int i = size_; i >= pos; --i)//包括\0都后移一位
				str_[i + 1] = str_[i];

			size_++;
		}

		return str_ + pos_;
	}
	void string::push_back(char c)
	{
		insert(end(), c);
	}
	string::iterator string::erase(iterator p)
	{
		int pos = p - begin();
		for (int i = pos; i < size_ - 1; ++i)
			str_[i] = str_[i + 1];
		if (pos >= 0 && pos < size_)
			size_--;

		return p;
	}

	string& string::erase(size_t pos, size_t len)
	{
		if (len == string::npos || pos + len >= size_)
		{
			size_ = pos;
			str_[pos] = '\0';
		}
		else
		{
			int pre = pos, next = pos + len;
			while (next <= size_)
			{
				str_[pre] = str_[next];
				pre++;
				next++;
			}
			size_ -= len;
			str_[size_] = '\0';
		}
		return *this;
	}

	string string::substr(size_t pos, size_t len)
	{
		string s;
		if (len == string::npos || pos + len > size_)
		{
			char* tmp = new char[size_ - pos + 1];//给\0也要开空间
			memcpy(tmp, str_ + pos, size_ - pos + 1);
			s = tmp;
		}
		else
		{
			char* tmp = new char[len + 1];
			memcpy(tmp, str_ + pos, len);
			tmp[len] = '\0';
			s = tmp;
		}
		return s;
	}
	size_t string::find(const char* str, size_t pos)
	{
		int len = strlen(str);//计算出str字符串的长度
		int pos_ = -1;
		for (int i = pos; i < size_ - len; ++i)//从pos位置开始遍历，找接下来的子串是否含有str
		{
			string tmp = substr(i, len);//复用string切割函数
			if (strcmp(tmp.str_, str) == 0)//字符串比较函数来比较
			{
				pos_ = i;
				break;
			}
		}
		return pos_ == -1 ? string::npos : pos_;//如果没有找到，就返回npos
	}
	size_t string::find(const string& s, size_t pos)
	{
		int pos_ = -1;
		for (int i = pos; i < size_ - s.size(); ++i)
		{
			string tmp = substr(i, s.size());
			if (strcmp(s.str_, tmp.str_) == 0)
			{
				pos_ = i;
				break;
			}
		}
		return pos_ == -1 ? string::npos : pos_;
	}
	void string::swap(string& s)
	{
		std::swap(s.capacity_, capacity_);
		std::swap(s.str_, str_);
		std::swap(s.size_, size_);
	}

	string& string::operator= (const string& str)
	{
		string tmp(str);
		tmp.swap(*this);

		return *this;
	}void swap(string& x, string& y)
	{
		x.swap(y);
	}
	
	string::~string()
	{
		size_ = 0;
		capacity_ = 0;
		delete[] str_;
		str_ = nullptr;
	}

	istream& operator>> (istream& is, string& str)
	{
		str.clear();
		char buffer[128];
		int i = 0;
		char ch = is.get();
		while (ch != ' ' && ch != '\n')
		{
			buffer[i++] = ch;
			if (i == 127)
			{
				buffer[i] = '\0';
				str += buffer;
				i = 0;
			}
			ch = is.get();
		}

		if (i > 0)
		{
			buffer[i] = '\0';
			str += buffer;
		}
		return is;
	}
	ostream& operator<< (ostream& os, const string& str)
	{
		for (auto ch : str)
			os << ch;
		return os;
	}
	istream& getline(istream& is, string& str)
	{
		str.clear();
		char buffer[128];
		int i = 0;
		char ch = is.get();
		while (ch != '\n')
		{
			buffer[i++] = ch;
			if (i == 127)
			{
				buffer[i] = '\0';
				str += buffer;
				i = 0;
			}
			ch = is.get();
		}

		if (i > 0)
		{
			buffer[i] = '\0';
			str += buffer;
		}
		return is;
	}
	string operator+ (const string& lhs, const string& rhs)
	{
		string tmp(lhs);
		tmp += rhs;
		return tmp;
	}
	string operator+ (const string& lhs, const char* rhs)
	{
		string tmp(lhs);
		tmp += rhs;
		return tmp;
	}
	string operator+ (const char* lhs, const string& rhs)
	{
		string tmp(lhs);
		tmp += rhs;
		return tmp;
	}
	string operator+ (const string& lhs, char   rhs)
	{
		string tmp(lhs);
		tmp += rhs;
		return tmp;
	}
	string operator+ (char lhs, const string& rhs)
	{
		string tmp(1, lhs);
		tmp += rhs;
		return tmp;
	}
	void Test_string1()//测试迭代器和构造函数以及赋值运算符重载
	{
		string s1;//默认构造
		string s2("520");
		string s3(s2);//拷贝构造
		string s4(4, 'a');

		cout << "s1: " << s1 << "s2: " << s2 << " s3: " << s3 << " s4:" << s4 << endl;//<< 操作符重载
		s1 = s3;//赋值运算符
		cout << "s1: " << s1 << "s2:" << s2 << " s3: " << s3 << " s4:" << s4 << endl;//<< 操作符重载
		cin >> s1;
		cout << "s1: " << s1 << "s2:" << s2 << " s3: " << s3 << " s4:" << s4 << endl;//<< 操作符重载

		string s5;
		//+=操作符重载
		s5 += '1';
		s5 += "314";
		s5 += s2;
		cout << "s5: " << s5 << endl;

		//+操作符重载
		string firstlevel("com");
		string secondlevel("cplusplus");
		string scheme("http://");
		string hostname;
		string url;

		hostname = "www." + secondlevel + '.' + firstlevel;
		url = scheme + hostname;

		cout << "url: " << url << '\n';

		//insert、erase函数
		string s6("1520");
		string s7("314");
		s6.insert(1, s7);
		cout << "s6: " << s6 << endl;
		s6.insert(s6.begin(), 'w');
		cout << "s6: " << s6 << endl;
		s6.erase(s6.begin());
		cout << "s6: " << s6 << endl;
		s6.erase(s6.end());
		cout << "s6: " << s6 << endl;
		s6.erase(0, 4);
		cout << s6 << endl;

		//find函数
		string s8("xxxxxlovexxxxxlovexxxxlove");
		string str1("lovexxxxxx");
		const char* str2 = "xxl";
		size_t pos1 = s8.find(str1, 0);//从下标7开始往后找
		if (pos1 != string::npos)
		{
			cout << "找到了!!!!首次出现的位置是" << pos1 << endl;
		}
		else
		{
			cout << "没有找到" << endl;
		}

		size_t pos2 = s8.find(str2, 0);//从下标7开始往后找
		if (pos2 != string::npos)
		{
			cout << "找到了!!!!位置是" << pos2 << endl;
		}
		else
		{
			cout << "没有找到" << endl;
		}

		//substr
		string s9("love and help");
		cout << "s9:" << s9.substr(9, 4) << endl;//从s的下标9位置开始的连续4个字符，help

		//append函数
		string str;
		string str4("Writing ");
		string str5("print 10 and then 5 more");

		// used in the same order as described above:
		str.append(str4);                       // "Writing "

		str.append("here: ");                   // "here: "
		str.append(10u, '.');                    // ".........."

		cout << "str:" << str << '\n';

		//swap函数
		cout << "s1: " << s1 << " s2: " << s2 << endl;
		swap(s1, s2);
		cout << "s1: " << s1 << " s2: " << s2 << endl;

		//resize、shrink_to_fit
		string s10("reserve");
		s10.push_back('s');

		cout << "size: " << s10.size() << "capacity: " << s10.capacity() << endl;
		s10.shrink_to_fit();
		cout << "size: " << s10.size() << "capacity: " << s10.capacity() << endl;
		s10.resize(1000,'5');
		cout << "size: " << s10.size() << "capacity: " << s10.capacity() << endl;
		s10.shrink_to_fit();
		cout << "size: " << s10.size() << "capacity: " << s10.capacity() << endl;

		//size、length
		string s11 = "xxxxxx";
		cout << "size: " << s11.size() << endl;
		cout << "length: " << s11.length() << endl;

		//capacity
		string  s12("xxxxxxxxxxxxx");
		int pre = s12.capacity();
		for (int i = 0; i < 100000; i++)
		{
			s12 += 'x';
			if (pre < s12.capacity())
			{
				cout << "i: " << i << "capacity: " << "增加的字节倍数：" << 1.0 * s12.capacity() / pre << " " << s12.capacity() << endl;
				pre = s12.capacity();
			}
		}

		//clear函数
		s12.clear();
		cout << "s12: " << s12 << endl;
	}
}